package utils

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

func Md5(data []byte) string {
	has := md5.Sum(data)
	return fmt.Sprintf("%x", has)
}

func Md5Reader(in io.Reader) string {
	md5hash := md5.New()
	if _, err := io.Copy(md5hash, in); err != nil {
		return ""
	}
	return fmt.Sprintf("%x", md5hash.Sum(nil))
}

//解析过期时间
func ParseExpire(expiresIn int64) time.Time {
	now := time.Now()
	d, _ := time.ParseDuration(fmt.Sprintf("%ds", expiresIn))
	return now.Add(d)
}

func Random(c int) (b []byte) {
	src := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz")
	n := len(src)
	buf := &bytes.Buffer{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < c; i += 1 {
		index := r.Intn(n)
		buf.WriteByte(src[index])
	}
	b = buf.Bytes()
	return
}

func Scheme(req *http.Request) string {
	if req.TLS != nil {
		return "https"
	}
	if scheme := req.Header.Get("X-Forwarded-Proto"); scheme != "" {
		return scheme
	}
	if scheme := req.Header.Get("X-Forwarded-Protocol"); scheme != "" {
		return scheme
	}
	if ssl := req.Header.Get("X-Forwarded-Ssl"); ssl == "on" {
		return "https"
	}
	if scheme := req.Header.Get("X-Url-Scheme"); scheme != "" {
		return scheme
	}
	return "http"
}

func FileExists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

func ValidatePath(dirs []string) (string, bool) {
	for _, v := range dirs {
		if len(v) > 0 {
			v, _ = filepath.Abs(v)
			if FileExists(v) {
				return v, true
			}
		}
	}
	return "", false
}

func CreateDirIfNotExist(file string) error {
	dir := filepath.Dir(file)
	if !FileExists(dir) {
		return os.MkdirAll(dir, os.ModePerm)
	}
	return nil
}

func IsWindows() bool {
	if runtime.GOOS == "windows" {
		return true
	}
	return false
}

func GetAppPath() string {
	if path, err := filepath.Abs(filepath.Dir(os.Args[0])); err == nil {
		return path
	}
	return os.Args[0]
}

func GetFileAbs(path string) string {
	if path, err := filepath.Abs(path); err == nil {
		return path
	}
	return os.Args[0]
}

type CompareFunc func(interface{}, interface{}) int

func indexOf(a []interface{}, e interface{}, cmp CompareFunc) int {
	n := len(a)
	for i := 0; i < n; i++ {
		if cmp(e, a[i]) == 0 {
			return i
		}
	}
	return -1
}

func ZmObjectName(input, z string) string {
	if z == "" {
		return ""
	}
	v := []interface{}{".mp4", ".avi", ".flv", ".mov", ".3gp", ".wmv", ".dat", ".mkv", ".qt"}
	output := ""
	idx := strings.LastIndex(input, ".")
	if idx != -1 {
		fIdx := indexOf(v, input[idx:], func(a interface{}, b interface{}) int {
			s1 := a.(string)
			s2 := b.(string)
			return strings.Compare(s1, s2)
		})
		if fIdx == -1 {
			return ""
		}
		output = input[:idx] + "/" + z + input[idx:]
	}
	return output
}
